#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kobject.h>
#include <linux/device.h>


//创建无设备的sys目录,使用kobject_create_and_add创建kobject:
//  myKobj = kobject_create_and_add("aHanJKobj", NULL ) ;
//使用 sysfs_create_file 在/sys目录下创建子目录及属性/sys/aHanJKobj/HanJKobjAttr_1 :
//  ret = sysfs_create_file(myKobj,  &attr_1 ) ;
static struct kobject *myKobj , *myKobj1 ;
static struct attribute  attr_1 = {
	.name = "HanJKobjAttr_1",
	.mode = 0644,
};

static struct attribute  attr_2 = {
	.name = "HanJKobjAttr_2",
	.mode = 0644,
};

static struct attribute  attr_3 = {
	.name = "HanJKobjAttr_3",
	.mode = 0644,
};


static struct attribute  attr1 = {
	.name = "HanJKobjAttr1",
	.mode = 0644,
};

//创建无class的设备,在/sys/devices 可以创建目录,比如 /sys/devices/devNoclss/nclsss
static struct device devNoCls;
static ssize_t nocls_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	printk("HanJ %s\n" , __func__ ) ;	
    return 0 ;
}
static ssize_t nocls_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    printk("HanJ %s\n" , __func__ ) ;	
	return count;
}

static DEVICE_ATTR(nclsss, 0664, nocls_show, nocls_store);

static int noCls_device_init(void)
{
	int ret  ;
    dev_set_name(&devNoCls, "devNoClss");
    devNoCls.parent = NULL;
    devNoCls.release = (void (*)(struct device *)) (void *) (int (*)(void)) 0;

    ret = device_register(&devNoCls);
	printk("HanJ device_register NoClass return %d\n" ,ret ) ;
	return 0;
}

static void noCls_device_exit(void)
{
    device_unregister(&devNoCls);
}

//创建有class的设备,会在/sys/class/testCls0下出现属性
//在/sys/devices/virtual/testCls0/Obj1ofTestCls0
static  struct class *cls;
static  struct device *devc;

static ssize_t test_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	printk("HanJ %s\n" , __func__ ) ;	
    return 0 ;
}

static ssize_t test_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    printk("HanJ %s\n" , __func__ ) ;	
	return count;
}

static DEVICE_ATTR(test, 0664, test_show, test_store);

static int __init my_init(void)
{	
	int ret = 0;
	
	myKobj = kobject_create_and_add("aHanJKobj", NULL ) ;
	if( !myKobj )  {
		printk("HanJ  kobject_create_and_add fail\n" ) ;
		return -1 ;
	}
	ret = sysfs_create_mount_point( myKobj , "testdir" ) ; 
	printk("HanJ sysfs_create_mount_point return %d\n" , ret ) ;
	ret = sysfs_create_file(myKobj,  &attr_1 ) ;
	printk("HanJ sysfs_create_file 0 attr_1 return %d\n" , ret ) ;
	ret = sysfs_create_file(myKobj,  &attr_2 ) ;
	printk("HanJ sysfs_create_file 0 attr_2 return %d\n" , ret ) ;
	ret = sysfs_create_file(myKobj,  &attr_3 ) ;
	printk("HanJ sysfs_create_file 0 attr_3 return %d\n" , ret ) ;

	myKobj1 = kobject_create_and_add("HanJKobj1", NULL ) ;
	if( !myKobj1 )  {
		printk("HanJ  1 kobject_create_and_add fail\n" ) ;
		return -1 ;
	}
	ret = sysfs_create_file(myKobj1, &attr1 ) ;
	
	printk("HanJ sysfs_create_file 1 return %d\n" , ret ) ;
	
	//create class
    cls = class_create(THIS_MODULE, "testCls0" );
    printk("HanJ class_create return %x\n" , (unsigned int)cls ) ;
	//create device
    devc = device_create(cls,NULL,0,NULL, "Obj1ofTestCls0");  
	printk("HanJ device_create return %x\n" , (unsigned int)devc ) ;
    ret = device_create_file(devc,&dev_attr_test );
	printk("HanJ device_create_file return %d\n" , ret ) ;
	
	noCls_device_init() ;	 
	ret = device_create_file(&devNoCls,&dev_attr_nclsss );
	printk("HanJ device_create_file noCls return %d\n" , ret ) ;
	
	return ret ;
}


static void __exit my_exit(void)
{
	sysfs_remove_mount_point( myKobj , "testdir" ) ;
	kobject_del(myKobj);
	kobject_put(myKobj);
	kobject_del(myKobj1);
	kobject_put(myKobj1);
	noCls_device_exit() ;
	printk("HanJ exit\n" );
}

module_init(my_init);
module_exit(my_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Example of using kernfs");

